﻿// Decompiled with JetBrains decompiler
// Type: MCM.LightInject.ImmutableMapTree`1
// Assembly: MCMv5, Version=5.10.2.0, Culture=neutral, PublicKeyToken=null
// MVID: 7AB326B9-B2B4-41C2-9177-68E944071101
// Assembly location: D:\steam\steamapps\workshop\content\261550\2859238197\bin\Win64_Shipping_Client\MCMv5.dll

using System;
using System.Diagnostics.CodeAnalysis;

#nullable disable
namespace MCM.LightInject
{
  [ExcludeFromCodeCoverage]
  internal sealed class ImmutableMapTree<TValue>
  {
    public static readonly ImmutableMapTree<TValue> Empty = new ImmutableMapTree<TValue>();
    public readonly int Key;
    public readonly TValue Value;
    public readonly ImmutableMapTree<TValue> Left;
    public readonly ImmutableMapTree<TValue> Right;
    public readonly int Height;
    public readonly bool IsEmpty;

    public ImmutableMapTree(int key, TValue value, ImmutableMapTree<TValue> hashTree)
    {
      this.Key = key;
      this.Value = value;
      this.Height = hashTree.Height;
      this.Left = hashTree.Left;
      this.Right = hashTree.Right;
    }

    public ImmutableMapTree(
      int key,
      TValue value,
      ImmutableMapTree<TValue> left,
      ImmutableMapTree<TValue> right)
    {
      switch (left.Height - right.Height)
      {
        case -2:
          if (right.IsLeftHeavy())
            right = ImmutableMapTree<TValue>.RotateRight(right);
          this.Key = right.Key;
          this.Value = right.Value;
          this.Left = new ImmutableMapTree<TValue>(key, value, left, right.Left);
          this.Right = right.Right;
          break;
        case 2:
          if (left.IsRightHeavy())
            left = ImmutableMapTree<TValue>.RotateLeft(left);
          this.Key = left.Key;
          this.Value = left.Value;
          this.Right = new ImmutableMapTree<TValue>(key, value, left.Right, right);
          this.Left = left.Left;
          break;
        default:
          this.Key = key;
          this.Value = value;
          this.Left = left;
          this.Right = right;
          break;
      }
      this.Height = 1 + Math.Max(this.Left.Height, this.Right.Height);
    }

    private ImmutableMapTree() => this.IsEmpty = true;

    private static ImmutableMapTree<TValue> RotateLeft(ImmutableMapTree<TValue> node)
    {
      return new ImmutableMapTree<TValue>(node.Right.Key, node.Right.Value, new ImmutableMapTree<TValue>(node.Key, node.Value, node.Left, node.Right.Left), node.Right.Right);
    }

    private static ImmutableMapTree<TValue> RotateRight(ImmutableMapTree<TValue> node)
    {
      return new ImmutableMapTree<TValue>(node.Left.Key, node.Left.Value, node.Left.Left, new ImmutableMapTree<TValue>(node.Key, node.Value, node.Left.Right, node.Right));
    }

    private bool IsLeftHeavy() => this.Left.Height > this.Right.Height;

    private bool IsRightHeavy() => this.Right.Height > this.Left.Height;
  }
}
